package com.soft.service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.soft.entity.Schedule;
import com.soft.entity.Team;
import com.soft.entity.TeamMember;
import com.soft.entity.User;
import com.soft.entity.Worklog;
import com.soft.mapper.ScheduleMapper;
import com.soft.mapper.TeamMapper;
import com.soft.mapper.TeamMemberMapper;
import com.soft.mapper.UserMapper;
import com.soft.mapper.WorklogMapper;

/**
 * 统计服务（只加注释，不改逻辑）：
 * - leaderMetrics(userId, days)：面向“负责人/领导”的我的团队视角指标（仅我为 leader 的团队 + 我创建的团队）
 *   - 返回：teams（团队简要信息）、stats（团队数/近days工作日志数/日程数）、trend（近days每天工作日志计数）
 *           scheduleStatus（团队内日程状态分布）、topTeamsByWorklogs、topUsersByWorklogs、recentWorklogs、
 *           upcomingSchedules（含创建人昵称）、teamDetails（每个团队成员/日程/近days日志数）
 * - adminMetrics(days)：管理员全局视角指标（公司级）
 *   - 返回：与 leaderMetrics 类似，但范围为全量团队/用户；top榜基于全量 worklog 聚合
 * - getCompanyKanbanData()：公司级看板统计（各状态任务数量 + 团队分布与合计），用于首页环形/柱状展示
 * - getCompanyTaskUpdates(limit)：公司级任务更新记录（按更新时间倒序），含用户/团队名、动作（创建/开始/完成/取消/更新）
 * 说明：为前端答辩展示提供“可读的”汇总结构与字段说明，未更改任何业务逻辑
 */
@Service
public class MetricsService {

    @Autowired
    private TeamMemberMapper teamMemberMapper;
    @Autowired
    private TeamMapper teamMapper;
    @Autowired
    private WorklogMapper worklogMapper;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private UserMapper userMapper;

    public Map<String, Object> leaderMetrics(Integer userId, int days) {
        Map<String, Object> m = new HashMap<>();
    // STEP 1：定位范围
    // - 找到“我作为 leader 的团队” + “我创建的团队”（两者合并去重）
    // - 注意：有些数据创建者即负责人，但 team_member 可能缺记录，故需同时查 team.creator_id
    List<TeamMember> myMemberships = teamMemberMapper.selectList(new QueryWrapper<TeamMember>()
        .eq("user_id", userId));
    List<TeamMember> myLeaderTeams = myMemberships.stream()
        .filter(tm -> tm.getTeamRole() != null && tm.getTeamRole().equalsIgnoreCase("leader"))
        .collect(Collectors.toList());
    Set<Integer> teamIds = myLeaderTeams.stream().map(TeamMember::getTeamId).collect(Collectors.toSet());
    // 同时纳入我创建的团队
    List<Team> createdTeams = teamMapper.selectList(new QueryWrapper<Team>().eq("creator_id", userId));
    teamIds.addAll(createdTeams.stream().map(Team::getTeamId).collect(Collectors.toSet()));
    // 边界：没有团队则直接返回空聚合
    if (teamIds.isEmpty()) {
            m.put("teams", List.of());
            m.put("stats", Map.of("teamCount", 0, "worklogCount", 0, "scheduleCount", 0));
            m.put("trend", List.of());
            return m;
        }
    List<Team> teams = teamIds.isEmpty() ? List.of() : teamMapper.selectList(new QueryWrapper<Team>().in("team_id", teamIds));

    // STEP 2：构建“近 days 天”趋势（每日工作日志计数）
    LocalDate today = LocalDate.now();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("MM-dd");
    List<Map<String, Object>> trend = new ArrayList<>();
    int totalWorklogs = 0;
    for (int i = days - 1; i >= 0; i--) {
        LocalDate d = today.minusDays(i);
        int cnt = worklogMapper.selectCount(new QueryWrapper<Worklog>()
            .in("related_team_id", teamIds)
            .eq("log_date", d.toString())).intValue();
        totalWorklogs += cnt;
        Map<String, Object> p = new HashMap<>();
        p.put("date", df.format(d));
        p.put("worklogs", cnt);
        trend.add(p);
    }

    // STEP 3：汇总统计（团队数/近 N 天工作日志总量/日程总量）
        int teamCount = teams.size();
        int scheduleCount = scheduleMapper.selectCount(new QueryWrapper<Schedule>().in("team_id", teamIds)).intValue();

        Map<String, Object> stats = new HashMap<>();
        stats.put("teamCount", teamCount);
        stats.put("worklogCount", totalWorklogs);
        stats.put("scheduleCount", scheduleCount);
    // STEP 4：日程状态分布（todo/doing/done/canceled）
    Map<String, Integer> scheduleStatus = new HashMap<>();
    for (String s : List.of("todo","doing","done","canceled")) {
        int c = scheduleMapper.selectCount(new QueryWrapper<Schedule>()
            .in("team_id", teamIds)
            .eq("status", s)).intValue();
        scheduleStatus.put(s, c);
    }
    // STEP 5：Top 团队（按近 N 天工作日志计数排序，取前 5）
    LocalDate from = today.minusDays(days - 1);
    List<Map<String, Object>> topTeamList = new ArrayList<>();
    // group by in Java（为兼容性与简化）
    List<Worklog> wlScope = worklogMapper.selectList(new QueryWrapper<Worklog>()
        .in("related_team_id", teamIds)
        .ge("log_date", from.toString()));
    Map<Integer, Long> teamWl = wlScope.stream()
        .collect(Collectors.groupingBy(Worklog::getRelatedTeamId, Collectors.counting()));
    teamWl.entrySet().stream()
        .sorted(Map.Entry.<Integer, Long>comparingByValue(Comparator.reverseOrder()))
        .limit(5)
        .forEach(e -> {
            Team t = teams.stream().filter(x -> x.getTeamId().equals(e.getKey())).findFirst().orElse(null);
            Map<String, Object> row = new HashMap<>();
            row.put("teamId", e.getKey());
            row.put("teamName", t != null ? t.getTeamName() : ("#"+e.getKey()));
            row.put("worklogs", e.getValue().intValue());
            topTeamList.add(row);
        });
    // STEP 6：Top 用户（按近 N 天工作日志计数排序，取前 5）
    Map<Integer, Long> userWl = wlScope.stream()
        .collect(Collectors.groupingBy(Worklog::getCreatorId, Collectors.counting()));
    List<Integer> topUserIds = userWl.entrySet().stream()
        .sorted(Map.Entry.<Integer, Long>comparingByValue(Comparator.reverseOrder()))
        .limit(5)
        .map(Map.Entry::getKey).collect(Collectors.toList());
    Map<Integer, String> userNames = new HashMap<>();
    if (!topUserIds.isEmpty()) {
    List<User> us = userMapper.selectList(new QueryWrapper<User>().in("user_id", topUserIds));
        for (User u : us) userNames.put(u.getUserId(), u.getUsername());
    }
    List<Map<String, Object>> topUserList = new ArrayList<>();
    for (Integer uid : topUserIds) {
        Map<String, Object> row = new HashMap<>();
        row.put("userId", uid);
        row.put("username", userNames.getOrDefault(uid, String.valueOf(uid)));
        row.put("worklogs", userWl.getOrDefault(uid, 0L).intValue());
        topUserList.add(row);
    }
    // STEP 7：最近工作日志（近 N 天内，最多 10 条）
    List<Worklog> recentWl = worklogMapper.selectList(new QueryWrapper<Worklog>()
        .in("related_team_id", teamIds)
        .ge("log_date", from.toString())
        .orderByDesc("create_time")
        .last("limit 10"));
    List<Map<String, Object>> recentWorklogs = recentWl.stream().map(w -> {
        Map<String, Object> r = new HashMap<>();
        r.put("worklogId", w.getWorklogId());
        r.put("title", w.getTitle());
        r.put("logDate", w.getLogDate() == null ? null : w.getLogDate().toString());
        r.put("teamId", w.getRelatedTeamId());
        r.put("creatorId", w.getCreatorId());
        r.put("createTime", w.getCreateTime() == null ? null : w.getCreateTime().toString().replace('T',' '));
        return r;
    }).collect(Collectors.toList());
    // STEP 8：未来日程（未来 days 天内，最多 10 条）
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime until = now.plusDays(days);
    List<Schedule> upcoming = scheduleMapper.selectList(new QueryWrapper<Schedule>()
        .in("team_id", teamIds)
        .between("start_time", now, until)
        .orderByAsc("start_time")
        .last("limit 10"));
    // 关联用户名（用于前端展示创建者昵称/用户名）
    Set<Integer> creatorIds = upcoming.stream().map(Schedule::getCreatorId).collect(Collectors.toSet());
    Map<Integer, String> creatorNames = new HashMap<>();
    if (!creatorIds.isEmpty()) {
        List<User> creators = userMapper.selectList(new QueryWrapper<User>().in("user_id", creatorIds));
        for (User u : creators) creatorNames.put(u.getUserId(), u.getUsername());
    }
    
    List<Map<String, Object>> upcomingSchedules = upcoming.stream().map(s -> {
        Map<String, Object> r = new HashMap<>();
        r.put("scheduleId", s.getScheduleId());
        r.put("title", s.getTitle());
        r.put("content", s.getContent());
        r.put("status", s.getStatus());
        r.put("priority", s.getPriority());
        r.put("teamId", s.getTeamId());
        r.put("creatorId", s.getCreatorId());
        r.put("creatorName", creatorNames.getOrDefault(s.getCreatorId(), "未知用户"));
        r.put("location", s.getLocation());
        r.put("startTime", s.getStartTime() == null ? null : s.getStartTime().toString().replace('T',' '));
        r.put("endTime", s.getEndTime() == null ? null : s.getEndTime().toString().replace('T',' '));
        r.put("createTime", s.getCreateTime() == null ? null : s.getCreateTime().toString().replace('T',' '));
        r.put("updateTime", s.getUpdateTime() == null ? null : s.getUpdateTime().toString().replace('T',' '));
        r.put("remindTime", s.getRemindTime() == null ? null : s.getRemindTime().toString().replace('T',' '));
        return r;
    }).collect(Collectors.toList());
    // STEP 9：团队详情（成员数/日程数/近 N 天日志数）
    List<Map<String, Object>> teamDetails = new ArrayList<>();
    Set<Integer> teamIdSet = new HashSet<>(teamIds);
    Map<Integer, Long> teamWlRange = wlScope.stream().collect(Collectors.groupingBy(Worklog::getRelatedTeamId, Collectors.counting()));
    for (Team t : teams) {
        if (!teamIdSet.contains(t.getTeamId())) continue;
        int memCnt = teamMemberMapper.selectCount(new QueryWrapper<TeamMember>().eq("team_id", t.getTeamId())).intValue();
        int schCnt = scheduleMapper.selectCount(new QueryWrapper<Schedule>().eq("team_id", t.getTeamId())).intValue();
        int wlCnt = teamWlRange.getOrDefault(t.getTeamId(), 0L).intValue();
        Map<String, Object> r = new HashMap<>();
        r.put("teamId", t.getTeamId());
        r.put("teamName", t.getTeamName());
        r.put("members", memCnt);
        r.put("schedules", schCnt);
        r.put("worklogs", wlCnt);
        teamDetails.add(r);
    }

    // STEP 10：组装返回
    m.put("teams", teams.stream().map(this::toTeamView).toList());
    m.put("stats", stats);
    m.put("trend", trend);
    m.put("scheduleStatus", scheduleStatus);
    m.put("topTeamsByWorklogs", topTeamList);
    m.put("topUsersByWorklogs", topUserList);
    m.put("recentWorklogs", recentWorklogs);
    m.put("upcomingSchedules", upcomingSchedules);
    m.put("teamDetails", teamDetails);
        return m;
    }

    public Map<String, Object> adminMetrics(int days) {
        Map<String, Object> m = new HashMap<>();
    // STEP 1：全量团队范围
    List<Team> teams = teamMapper.selectList(new QueryWrapper<>());

    // STEP 2：近 days 天趋势（全部工作日志计数）
    LocalDate today = LocalDate.now();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("MM-dd");
    List<Map<String, Object>> trend = new ArrayList<>();
    int totalWorklogs = 0;
    for (int i = days - 1; i >= 0; i--) {
        LocalDate d = today.minusDays(i);
        int cnt = worklogMapper.selectCount(new QueryWrapper<Worklog>()
            .eq("log_date", d.toString())).intValue();
        totalWorklogs += cnt;
        Map<String, Object> p = new HashMap<>();
        p.put("date", df.format(d));
        p.put("worklogs", cnt);
        trend.add(p);
    }

    // STEP 3：汇总统计（团队数/近 N 天工作日志总量/日程总量）
    int teamCount = teams.size();
        int scheduleCount = scheduleMapper.selectCount(new QueryWrapper<>()).intValue();

        Map<String, Object> stats = new HashMap<>();
        stats.put("teamCount", teamCount);
        stats.put("worklogCount", totalWorklogs);
        stats.put("scheduleCount", scheduleCount);

    // STEP 4：日程状态分布（全量）：todo/doing/done/canceled 计数
        Map<String, Integer> scheduleStatus = new HashMap<>();
        for (String s : List.of("todo","doing","done","canceled")) {
            int c = scheduleMapper.selectCount(new QueryWrapper<Schedule>().eq("status", s)).intValue();
            scheduleStatus.put(s, c);
        }
    // STEP 5：Top 团队 / Top 用户（近 N 天）：基于工作日志聚合
        LocalDate from = today.minusDays(days - 1);
        List<Worklog> wlScope = worklogMapper.selectList(new QueryWrapper<Worklog>().ge("log_date", from.toString()));
        Map<Integer, Long> teamWl = wlScope.stream()
            .filter(w -> w.getRelatedTeamId() != null) // 过滤null值
            .collect(Collectors.groupingBy(Worklog::getRelatedTeamId, Collectors.counting()));
        List<Map<String, Object>> topTeamList = teamWl.entrySet().stream()
                .sorted(Map.Entry.<Integer, Long>comparingByValue(Comparator.reverseOrder()))
                .limit(5)
                .map(e -> {
                    Team t = teams.stream().filter(x -> x.getTeamId().equals(e.getKey())).findFirst().orElse(null);
                    Map<String, Object> row = new HashMap<>();
                    row.put("teamId", e.getKey());
                    row.put("teamName", t != null ? t.getTeamName() : ("#"+e.getKey()));
                    row.put("worklogs", e.getValue().intValue());
                    return row;
                }).collect(Collectors.toList());
        Map<Integer, Long> userWl = wlScope.stream()
            .filter(w -> w.getCreatorId() != null) // 过滤null值
            .collect(Collectors.groupingBy(Worklog::getCreatorId, Collectors.counting()));
        List<Integer> topUserIds = userWl.entrySet().stream()
                .sorted(Map.Entry.<Integer, Long>comparingByValue(Comparator.reverseOrder()))
                .limit(5)
                .map(Map.Entry::getKey).collect(Collectors.toList());
        Map<Integer, String> userNames = new HashMap<>();
        if (!topUserIds.isEmpty()) {
        List<User> us = userMapper.selectList(new QueryWrapper<User>().in("user_id", topUserIds));
            for (User u : us) userNames.put(u.getUserId(), u.getUsername());
        }
        List<Map<String, Object>> topUserList = new ArrayList<>();
        for (Integer uid : topUserIds) {
            Map<String, Object> row = new HashMap<>();
            row.put("userId", uid);
            row.put("username", userNames.getOrDefault(uid, String.valueOf(uid)));
            row.put("worklogs", userWl.getOrDefault(uid, 0L).intValue());
            topUserList.add(row);
        }
    // STEP 6：最近工作日志（近 N 天内，最多 10 条）
        List<Worklog> recentWl = worklogMapper.selectList(new QueryWrapper<Worklog>()
                .ge("log_date", from.toString())
                .orderByDesc("create_time")
                .last("limit 10"));
        List<Map<String, Object>> recentWorklogs = recentWl.stream().map(w -> {
            Map<String, Object> r = new HashMap<>();
            r.put("worklogId", w.getWorklogId());
            r.put("title", w.getTitle());
            r.put("logDate", w.getLogDate() == null ? null : w.getLogDate().toString());
            r.put("teamId", w.getRelatedTeamId());
            r.put("creatorId", w.getCreatorId());
            r.put("createTime", w.getCreateTime() == null ? null : w.getCreateTime().toString().replace('T',' '));
            return r;
        }).collect(Collectors.toList());
    // STEP 7：未来日程（未来 days 天内，最多 10 条）
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime until = now.plusDays(days);
        List<Schedule> upcoming = scheduleMapper.selectList(new QueryWrapper<Schedule>()
                .between("start_time", now, until)
                .orderByAsc("start_time")
                .last("limit 10"));
        // 获取创建者信息
        Set<Integer> adminCreatorIds = upcoming.stream().map(Schedule::getCreatorId).collect(Collectors.toSet());
        Map<Integer, String> adminCreatorNames = new HashMap<>();
        if (!adminCreatorIds.isEmpty()) {
            List<User> adminCreators = userMapper.selectList(new QueryWrapper<User>().in("user_id", adminCreatorIds));
            for (User u : adminCreators) adminCreatorNames.put(u.getUserId(), u.getUsername());
        }
        
        List<Map<String, Object>> upcomingSchedules = upcoming.stream().map(s -> {
            Map<String, Object> r = new HashMap<>();
            r.put("scheduleId", s.getScheduleId());
            r.put("title", s.getTitle());
            r.put("content", s.getContent());
            r.put("status", s.getStatus());
            r.put("priority", s.getPriority());
            r.put("teamId", s.getTeamId());
            r.put("creatorId", s.getCreatorId());
            r.put("creatorName", adminCreatorNames.getOrDefault(s.getCreatorId(), "未知用户"));
            r.put("location", s.getLocation());
            r.put("startTime", s.getStartTime() == null ? null : s.getStartTime().toString().replace('T',' '));
            r.put("endTime", s.getEndTime() == null ? null : s.getEndTime().toString().replace('T',' '));
            r.put("createTime", s.getCreateTime() == null ? null : s.getCreateTime().toString().replace('T',' '));
            r.put("updateTime", s.getUpdateTime() == null ? null : s.getUpdateTime().toString().replace('T',' '));
            r.put("remindTime", s.getRemindTime() == null ? null : s.getRemindTime().toString().replace('T',' '));
            return r;
        }).collect(Collectors.toList());
    // STEP 8：团队详情（成员/日程/近 N 天日志）
        Map<Integer, Long> teamWlRange = wlScope.stream()
            .filter(w -> w.getRelatedTeamId() != null) // 过滤null值
            .collect(Collectors.groupingBy(Worklog::getRelatedTeamId, Collectors.counting()));
        List<Map<String, Object>> teamDetails = new ArrayList<>();
        for (Team t : teams) {
            if (t.getTeamId() == null) continue; // 跳过teamId为null的团队
            int memCnt = teamMemberMapper.selectCount(new QueryWrapper<TeamMember>().eq("team_id", t.getTeamId())).intValue();
            int schCnt = scheduleMapper.selectCount(new QueryWrapper<Schedule>().eq("team_id", t.getTeamId())).intValue();
            int wlCnt = teamWlRange.getOrDefault(t.getTeamId(), 0L).intValue();
            Map<String, Object> r = new HashMap<>();
            r.put("teamId", t.getTeamId());
            r.put("teamName", t.getTeamName());
            r.put("members", memCnt);
            r.put("schedules", schCnt);
            r.put("worklogs", wlCnt);
            teamDetails.add(r);
        }

    // STEP 9：组装返回
    m.put("teams", teams.stream().map(this::toTeamView).toList());
        m.put("stats", stats);
        m.put("trend", trend);
        m.put("scheduleStatus", scheduleStatus);
        m.put("topTeamsByWorklogs", topTeamList);
        m.put("topUsersByWorklogs", topUserList);
        m.put("recentWorklogs", recentWorklogs);
        m.put("upcomingSchedules", upcomingSchedules);
        m.put("teamDetails", teamDetails);
        return m;
    }

    private Map<String, Object> toTeamView(Team t) {
        Map<String, Object> mv = new HashMap<>();
        mv.put("teamId", t.getTeamId());
        mv.put("teamName", t.getTeamName());
        mv.put("description", t.getDescription());
        mv.put("creatorId", t.getCreatorId());
        // 格式化为 yyyy-MM-dd HH:mm:ss，避免前端/序列化的 JSR310 兼容性问题
        var ct = t.getCreateTime();
        mv.put("createTime", ct == null ? null : ct.toString().replace('T', ' '));
        return mv;
    }

    /**
     * 获取公司看板数据
     * 返回全公司的看板统计信息，包括各状态任务数量和团队分布
     */
    public Map<String, Object> getCompanyKanbanData() {
        Map<String, Object> result = new HashMap<>();
        
    // STEP 1：获取所有团队（作为全量范围）
        List<Team> allTeams = teamMapper.selectList(new QueryWrapper<>());
        
    // STEP 2：统计各状态的日程数量（全公司）
        Map<String, Integer> statusCounts = new HashMap<>();
        for (String status : List.of("todo", "doing", "done", "canceled")) {
            int count = scheduleMapper.selectCount(new QueryWrapper<Schedule>().eq("status", status)).intValue();
            statusCounts.put(status, count);
        }
        
    // STEP 3：统计各团队的任务数量（及成员数），便于前端做柱状图/表格
        List<Map<String, Object>> teamStats = new ArrayList<>();
        for (Team team : allTeams) {
            if (team.getTeamId() == null) continue;
            
            Map<String, Object> teamStat = new HashMap<>();
            teamStat.put("teamId", team.getTeamId());
            teamStat.put("teamName", team.getTeamName());
            
            // 统计该团队各状态任务数
            Map<String, Integer> teamStatusCounts = new HashMap<>();
            int totalTasks = 0;
            for (String status : List.of("todo", "doing", "done", "canceled")) {
                int count = scheduleMapper.selectCount(new QueryWrapper<Schedule>()
                    .eq("team_id", team.getTeamId())
                    .eq("status", status)).intValue();
                teamStatusCounts.put(status, count);
                totalTasks += count;
            }
            
            teamStat.put("statusCounts", teamStatusCounts);
            teamStat.put("totalTasks", totalTasks);
            
            // 获取团队成员数
            int memberCount = teamMemberMapper.selectCount(new QueryWrapper<TeamMember>()
                .eq("team_id", team.getTeamId())).intValue();
            teamStat.put("memberCount", memberCount);
            
            teamStats.add(teamStat);
        }
        
    // STEP 4：计算总任务数并组装回应
        int totalTasks = statusCounts.values().stream().mapToInt(Integer::intValue).sum();
        
        result.put("statusCounts", statusCounts);
        result.put("teamStats", teamStats);
        result.put("totalTasks", totalTasks);
        result.put("totalTeams", allTeams.size());
        
        return result;
    }

    /**
     * 获取公司级别的任务更新记录
     * 返回全公司最近的任务更新活动，包括日程创建、更新、状态变更等
     */
    public Map<String, Object> getCompanyTaskUpdates(Integer limit) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> taskUpdates = new ArrayList<>();
        
    // STEP 0：规范化入参（limit）
    if (limit == null || limit <= 0) {
            limit = 20; // 默认返回20条记录
        }
        
    // STEP 1：获取最近的日程记录（按更新时间排序，取 2*limit 以便后续筛选）
        QueryWrapper<Schedule> scheduleQw = new QueryWrapper<>();
        scheduleQw.orderByDesc("update_time");
        scheduleQw.last("LIMIT " + (limit * 2)); // 获取更多记录以便筛选
        List<Schedule> recentSchedules = scheduleMapper.selectList(scheduleQw);
        
    // STEP 2：缓存团队/用户名称映射，降低循环内查询
        List<Team> allTeams = teamMapper.selectList(new QueryWrapper<>());
        Map<Integer, String> teamNameMap = allTeams.stream()
            .collect(Collectors.toMap(Team::getTeamId, Team::getTeamName, (a, b) -> a));
        
    // 获取用户信息映射（优先昵称）
        List<User> allUsers = userMapper.selectList(new QueryWrapper<>());
        Map<Integer, String> userNameMap = allUsers.stream()
            .collect(Collectors.toMap(User::getUserId, 
                user -> user.getNickname() != null ? user.getNickname() : user.getUsername(), 
                (a, b) -> a));
        
    // STEP 3：逐条构建 taskUpdates（含任务标题、团队名、用户信息、动作、时间戳、状态与优先级）
        for (Schedule schedule : recentSchedules) {
            if (taskUpdates.size() >= limit) break;
            
            Map<String, Object> update = new HashMap<>();
            update.put("id", schedule.getScheduleId());
            update.put("taskTitle", schedule.getTitle());
            update.put("teamName", teamNameMap.getOrDefault(schedule.getTeamId(), "未知团队"));
            update.put("teamId", schedule.getTeamId());
            
            // 用户信息
            Map<String, Object> user = new HashMap<>();
            user.put("name", userNameMap.getOrDefault(schedule.getCreatorId(), "未知用户"));
            user.put("avatar", ""); // 可以后续扩展头像功能
            update.put("user", user);
            
            // 操作类型判定：优先比较创建/更新时间；若不同则结合 status 映射成具体动作
            String action;
            if (schedule.getCreateTime() != null && schedule.getUpdateTime() != null) {
                // 比较创建时间和更新时间，判断是创建还是更新
                if (schedule.getCreateTime().equals(schedule.getUpdateTime())) {
                    action = "创建了任务";
                } else {
                    // 根据状态判断具体操作
                    switch (schedule.getStatus() != null ? schedule.getStatus() : "todo") {
                        case "done":
                            action = "完成了任务";
                            break;
                        case "doing":
                            action = "开始了任务";
                            break;
                        case "canceled":
                            action = "取消了任务";
                            break;
                        default:
                            action = "更新了任务";
                    }
                }
            } else {
                action = "更新了任务";
            }
            update.put("action", action);
            
            // 时间戳（优先使用更新时间）
            update.put("timestamp", schedule.getUpdateTime() != null ? 
                schedule.getUpdateTime() : schedule.getCreateTime());
            
            // 状态
            update.put("status", schedule.getStatus());
            update.put("priority", schedule.getPriority());
            
            taskUpdates.add(update);
        }
        
    // STEP 4：按时间戳倒序排序，便于前端直接渲染
        taskUpdates.sort((a, b) -> {
            LocalDateTime timeA = (LocalDateTime) a.get("timestamp");
            LocalDateTime timeB = (LocalDateTime) b.get("timestamp");
            if (timeA == null && timeB == null) return 0;
            if (timeA == null) return 1;
            if (timeB == null) return -1;
            return timeB.compareTo(timeA);
        });
        
        result.put("taskUpdates", taskUpdates);
        result.put("total", taskUpdates.size());
        
        return result;
    }
}
